package com.yifeng.repo.storage.redis.client;

import com.yifeng.repo.storage.redis.configure.RedisProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;

/**
 * Created by daibing on 2020/2/7.
 */
public class JedisClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(JedisClient.class);
    private final RedisProperties properties;
    /**
     * Redis主从模式使用JedisPool即可（支撑分布式锁），注意：ShardedJedisPool不支持eval和evalsha函数，当前应该不需要。
     */
    private JedisPool jedisPool;

    public JedisClient(RedisProperties properties) {
        this.properties = properties;
    }

    public void init() throws URISyntaxException {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(properties.getMaxTotal());
        jedisPoolConfig.setMaxIdle(properties.getMaxIdle());
        jedisPoolConfig.setMinIdle(properties.getMinIdle());
        jedisPoolConfig.setNumTestsPerEvictionRun(1024);
        jedisPoolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(30));
        jedisPoolConfig.setMinEvictableIdleTime(Duration.ofSeconds(60));
        jedisPoolConfig.setMinEvictableIdleTime(Duration.ofSeconds(60));
        jedisPoolConfig.setSoftMinEvictableIdleTime(Duration.ofSeconds(10));
        jedisPoolConfig.setMaxWait(Duration.ofMillis(properties.getMaxWaitMillis()));
        jedisPoolConfig.setTestOnBorrow(properties.isTestOnBorrow());
        jedisPoolConfig.setTestWhileIdle(true);
        jedisPoolConfig.setTestOnReturn(false);
        jedisPoolConfig.setJmxEnabled(true);
        jedisPoolConfig.setBlockWhenExhausted(false);
        jedisPool = new JedisPool(jedisPoolConfig, new URI(properties.getUri()));
    }

    public void destroy() {
        if (jedisPool == null) {
            return;
        }
        jedisPool.close();
    }

    public Jedis get() {
        if (jedisPool.isClosed()) {
            throw new RuntimeException("Jedis pool is closed!");
        }
        return jedisPool.getResource();
    }

    public void close(Jedis res) {
        if (res == null) {
            return;
        }
        res.close();
    }

}
